package com.czk.model.singleton.practice;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @Author:ChenZhangKun
 * @Date: 2020/7/29 23:35
 */
public class Singleton {
    // 私有构造器
    private Singleton() {
    }

    // 1 枚举模式
    enum InnerEnum {
        // 天生单例
        INSTANCE;
        private Singleton singleton;

        InnerEnum() {
            singleton = new Singleton();
        }

        public Singleton getInstance() {
            return singleton;
        }
    }

    public static Singleton getInstance() {
        // 跳跃枚举内部的方法
        return InnerEnum.INSTANCE.getInstance();
    }

    public static void main(String[] args) throws InterruptedException {
        AtomicReference<Singleton> atomicReference1 = new AtomicReference<>();
        AtomicReference<Singleton> atomicReference2 = new AtomicReference<>();
        new Thread(() -> {
            atomicReference1.set(Singleton.getInstance());
        }).start();
        new Thread(() -> {
            atomicReference2.set(Singleton.getInstance());
        }).start();
        Thread.sleep(1 * 100);
        Singleton singleton = atomicReference1.get();
        Singleton singleton1 = atomicReference2.get();
        System.out.println(singleton.equals(singleton1));
    }
}

// 双重检查模式
class Singleton_2 {
    private Singleton_2() {
    }

    // 懒加载
    private static volatile Singleton_2 singleton_2;

    // 初始化
    public static Singleton_2 getInstance() {
        if (singleton_2 != null) {
            synchronized (Singleton_2.class) {
                // 双重检查
                if (singleton_2 != null) {
                    singleton_2 = new Singleton_2();
                }
            }
        }
        return singleton_2;
    }
}

// 静态内部类方式
class Singleton_3 {
    private Singleton_3() {
    }

    // 定义静态内部类
    private static class InnerClass {
        private static Singleton_3 singleton_3 = new Singleton_3();
    }

    // 返回
    public static Singleton_3 getInstance() {
        return InnerClass.singleton_3;
    }
}

/**
 * 枚举INSTANCE会在类加载初始化的时候创建,而Java类的加载和初始化过程都是线程安全的。
 * 枚举可避免反序列化破坏单例。
 */
class Singleton_4 {
    // 初始化私有化方法
    private Singleton_4() {
    }

    enum MyEnum {
        INSTANCE;
        private Singleton_4 singleton_4;

        // 私有化枚举构造函数
        private MyEnum() {
            singleton_4 = new Singleton_4();
        }

        public Singleton_4 getSingleton_4() {
            return singleton_4;
        }

    }

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        Thread t1 = new Thread(() -> {
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(MyEnum.INSTANCE.getSingleton_4());
        });
        Thread t2 = new Thread(() -> {
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(MyEnum.INSTANCE.getSingleton_4());
        });
        t1.start();
        t2.start();
        TimeUnit.SECONDS.sleep(2);
        countDownLatch.countDown();
    }
}
